home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-9.000 / irsim-9 / src / irsim / sim.c < prev    next >
C/C++ Source or Header  |  1993-01-15  |  15KB  |  663 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. /*
  16.  * The routines in this file handle network input (from sim files).
  17.  * The input routine "rd_network" replaces the work formerly done by presim.
  18.  * This version differs from the former in the following:
  19.  *  1. voltage drops across transistors are ignored (assumes transistors
  20.  *     driven by nodes with voltage drops have the same resistance as those
  21.  *     driven by a full swing).
  22.  *  2. static power calculations not performed (only useful for nmos anyhow).
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include "defs.h"
  27. #include "net.h"
  28. #include "globals.h"
  29. #include "net_macros.h"
  30.  
  31.  
  32. #define LSIZE        2000        /* size for input line buffer */
  33. #define    MAXARGS        20        /* max. # of arguments per line */
  34.  
  35.  
  36. public    nptr   VDD_node;        /* power supply nodes */
  37. public    nptr   GND_node;
  38.  
  39. public    lptr   on_trans;        /* always on transistors */
  40.  
  41. public    int    nnodes;            /* number of actual nodes */
  42. public    int    naliases;        /* number of aliased nodes */
  43. public    int    ntrans[ NTTYPES ];    /* number of txtors indexed by type */
  44.  
  45. public    lptr   freeLinks = NULL;    /* free list of Tlist structs */
  46. public    tptr   freeTrans = NULL;    /* free list of Transistor structs */
  47. public    nptr   freeNodes = NULL;    /* free list of Node structs */
  48.  
  49. public    tptr   tcap = NULL;        /* list of capacitor-transistors */
  50.  
  51. private    int    lineno;            /* current input file line number */
  52. private    char   *simfname;        /* current input filename */
  53. private    int    nerrs = 0;        /* # of erros found in sim file */
  54. private    int    isBinFile;        /* TRUE binary file, FALSE sim file */
  55.  
  56. private    tptr   rd_tlist;        /* list of transistors just read */
  57.  
  58. public
  59. #define    MIN_CAP        0.0005        /* minimum node capacitance (in pf) */
  60.  
  61.  
  62. #define    WARNING        0
  63. #define    WARN        1
  64. #define    MAX_ERRS    20
  65. #define    FATAL        (MAX_ERRS + 1)
  66.  
  67. private    char    bad_argc_msg[] = "Wrong number of args for '%c' (%d)\n";
  68.  
  69. #define    BAD_ARGC( CMD, ARGC, ARGV )            \
  70.   {                            \
  71.     error( simfname, lineno, bad_argc_msg, CMD, ARGC );    \
  72.     PrArgs( ARGC, ARGV );                \
  73.     CheckErrs( WARN );                    \
  74.     return;                        \
  75.   }                            \
  76.  
  77.  
  78. private void PrArgs( argc, argv )
  79.   int   argc;
  80.   char  *argv[];
  81.   {
  82.     while( argc-- != 0 )
  83.       (void) fprintf( stderr, "%s ", *argv++ );
  84.     (void) fputs( "\n", stderr );
  85.   }
  86.  
  87.  
  88. private void CheckErrs( n )
  89.   {
  90.     nerrs += n;
  91.     if( nerrs > MAX_ERRS )
  92.       {
  93.     if( n != FATAL )
  94.         (void) fprintf( stderr, "Too many errors in sim file <%s>\n",
  95.           simfname );
  96.     exit( 1 );
  97.       }
  98.   }
  99.  
  100.  
  101.  
  102. /*
  103.  * Traverse the transistor list and add the node connection-list.  We have
  104.  * to be careful with ALIASed nodes.  Note that transistors with source/drain
  105.  * connected VDD and GND nodes are not linked.
  106.  */
  107. private nptr connect_txtors()
  108.   {
  109.     register tptr  t, tnext;
  110.     register nptr  gate, src, drn, nd_list;
  111.     register int   type;
  112.     register long  visited;
  113.  
  114.     visited = VISITED;
  115.     nd_list = NULL;
  116.  
  117.     for( t = rd_tlist; t != NULL; t = tnext )
  118.       {
  119.     tnext = t->scache.t;
  120.     for( gate = t->gate; gate->nflags & ALIAS; gate = gate->nlink);
  121.     for( src = t->source; src->nflags & ALIAS; src = src->nlink );
  122.     for( drn = t->drain; drn->nflags & ALIAS; drn = drn->nlink );
  123.  
  124.     t->gate = gate;
  125.     t->source = src;
  126.     t->drain = drn;
  127.  
  128.     type = t->ttype;
  129.     t->state = ( type & ALWAYSON ) ? WEAK : UNKNOWN;
  130.     t->tflags = 0;
  131.  
  132.     ntrans[ type ]++;
  133.     if( src == drn or (src->nflags & drn->nflags & POWER_RAIL) )
  134.       {
  135.         t->ttype |= TCAP;        /* transistor is just a capacitor */
  136.         LINK_TCAP( t );
  137.       }
  138.     else
  139.       {
  140.         /* do not connect gate if ALWAYSON since they do not matter */
  141.         if( t->ttype & ALWAYSON )
  142.           {
  143.         CONNECT( on_trans, t );
  144.           }
  145.         else
  146.           {
  147.         CONNECT( t->gate->ngate, t );
  148.           }
  149.  
  150.         if( not (src->nflags & POWER_RAIL) )
  151.           {
  152.         CONNECT( src->nterm, t );
  153.         LINK_TO_LIST( src, nd_list, visited );
  154.           }
  155.         if( not (drn->nflags & POWER_RAIL) )
  156.           {
  157.         CONNECT( drn->nterm, t );
  158.         LINK_TO_LIST( drn, nd_list, visited );
  159.           }
  160.       }
  161.       }
  162.  
  163.     return( nd_list );
  164.   }
  165.  
  166.  
  167. /*
  168.  * node area and perimeter info (N sim command).
  169.  */
  170. private void node_info( targc, targv )
  171.   int   targc;
  172.   char  *targv[];
  173.   {
  174.     register nptr  n;
  175.  
  176.     if( targc != 8 )
  177.     BAD_ARGC( 'N', targc, targv );
  178.  
  179.     n = GetNode( targv[1] );
  180.  
  181.     n->ncap +=     atof( targv[4] ) * (CMA * LAMBDA2) +
  182.         atof( targv[5] ) * (CPA * LAMBDA2) +
  183.         atof( targv[6] ) * (CDA * LAMBDA2) +
  184.         atof( targv[7] ) * 2.0 * (CDP * LAMBDA);
  185.   }
  186.  
  187.  
  188. /*
  189.  * new format node area and perimeter info (M sim command).
  190.  */
  191. private void nnode_info( targc, targv )
  192.   int   targc;
  193.   char  *targv[];
  194.   {
  195.     register nptr  n;
  196.  
  197.     if( targc != 14 )
  198.     BAD_ARGC( 'M', targc, targv );
  199.  
  200.     n = GetNode( targv[1] );
  201.  
  202.     n->ncap +=    atof( targv[4] ) * (CM2A * LAMBDA2) +
  203.         atof( targv[5] ) * 2.0 * (CM2P * LAMBDA) +
  204.         atof( targv[6] ) * (CMA * LAMBDA2) +
  205.         atof( targv[7] ) * 2.0 * (CMP * LAMBDA) +
  206.         atof( targv[8] ) * (CPA * LAMBDA2) +
  207.         atof( targv[9] ) * 2.0 * (CPP * LAMBDA) +
  208.         atof( targv[10] ) * (CDA * LAMBDA) +
  209.         atof( targv[11] ) * 2.0 * (CDP * LAMBDA) +
  210.         atof( targv[12] ) * (CPDA * LAMBDA2) +
  211.         atof( targv[13] ) * 2.0 * (CPDP * LAMBDA);
  212.   }
  213.  
  214.  
  215. /*
  216.  * new transistor.  Implant specifies type.
  217.  * AreaPos specifies the argument number that contains the area (if any).
  218.  */
  219. private void newtrans( implant, targc, targv )
  220.   int   implant;
  221.   int   targc;
  222.   char  *targv[];
  223.   {
  224.     nptr           gate, src, drn, ntemp;
  225.     long           x, y, width, length;
  226.     double         cap;
  227.     register tptr  t;
  228.  
  229.     if( implant == RESIST )
  230.       {
  231.     if( targc != 4 )
  232.         BAD_ARGC( 'r', targc, targv );
  233.  
  234.     gate = VDD_node;
  235.     src = GetNode( targv[1] );
  236.     drn = GetNode( targv[2] );
  237.  
  238.     length = atof( targv[3] ) * LAMBDACM;
  239.     width = 0;
  240.       }
  241.     else
  242.       {
  243.     if( targc < 4 or targc > 11 )
  244.         BAD_ARGC( targv[0][0], targc, targv );
  245.  
  246.     gate = GetNode( targv[1] );
  247.     src = GetNode( targv[2] );
  248.     drn = GetNode( targv[3] );
  249.  
  250.     if( targc > 5 )
  251.       {
  252.         length = atof( targv[4] ) * LAMBDACM;
  253.         width = atof( targv[5] ) * LAMBDACM;
  254.         if( width <= 0 or length <= 0 )
  255.           {
  256.         error( simfname, lineno,
  257.           "Bad transistor width=%g or length=%g\n", width, length );
  258.         return;
  259.           }
  260.         if( targc > 7 )
  261.           {
  262.         x = atoi( targv[6] );
  263.         y = atoi( targv[7] );
  264.           }
  265.       }
  266.     else
  267.         width = length = 2 * LAMBDACM;
  268.  
  269.     cap = length * width * CTGA;
  270.       }
  271.  
  272.     NEW_TRANS( t );            /* create new transistor */
  273.  
  274.     t->ttype = implant;
  275.     t->gate = gate;
  276.     t->source = src;
  277.     t->drain = drn;
  278.  
  279.     if( targc > 7 )
  280.       {
  281.     t->x.pos = x;
  282.     t->y.pos = y;
  283.     EnterPos( t, TRUE );        /* Enter transistor position */
  284.       }
  285.     else
  286.     EnterPos( t, FALSE );        /* Enter transistor position */
  287.  
  288.     t->scache.t = rd_tlist;        /* link it to the list */
  289.     rd_tlist = t;
  290.  
  291.     t->r = requiv( implant, width, length );
  292.  
  293.         /* update node capacitances  */
  294.     gate->ncap += cap;
  295.  
  296.     if( config_flags & TDIFFCAP )
  297.       {
  298.     cap = CTDW * width + CTDE;
  299.     src->ncap += cap;
  300.     drn->ncap += cap;
  301.       }
  302.   }
  303.         
  304.  
  305. /*
  306.  * accept a bunch of aliases for a node (= sim command).
  307.  */
  308. private void alias( targc, targv )
  309.   int   targc;
  310.   char  *targv[];
  311.   {
  312.     register nptr  n, m;
  313.     register int   i;
  314.  
  315.     if( targc < 3 )
  316.     BAD_ARGC( '=', targc, targv );
  317.  
  318.     n = GetNode( targv[1] );
  319.  
  320.     for( i = 2; i < targc; i++ )
  321.       {
  322.     m = GetNode( targv[i] );
  323.     if( m == n )
  324.         continue;
  325.  
  326.     if( m->nflags & POWER_RAIL )
  327.         SWAP_NODES( m, n );
  328.  
  329.     if( m->nflags & POWER_RAIL )
  330.       {
  331.         error( simfname, lineno, "Can't alias the power supplies\n" );
  332.         continue;
  333.       }
  334.  
  335.     n->ncap += m->ncap;
  336.  
  337.     m->nlink = n;
  338.     m->nflags |= ALIAS;
  339.     m->ncap = 0.0;
  340.     nnodes--;
  341.     naliases++;
  342.       }
  343.   }
  344.  
  345.  
  346. /*
  347.  * node threshold voltages (t sim command).
  348.  */
  349. private void nthresh( targc, targv )
  350.   int   targc;
  351.   char  *targv[];
  352.   {
  353.     register nptr  n;
  354.  
  355.     if( targc != 4 )
  356.     BAD_ARGC( 't', targc, targv );
  357.  
  358.     n = GetNode( targv[1] );
  359.     n->vlow = atof( targv[2] );
  360.     n->vhigh = atof( targv[3] );
  361.   }
  362.  
  363.  
  364. /*
  365.  * User delay for a node (D sim command).
  366.  */
  367. private void ndelay( targc, targv )
  368.   int   targc;
  369.   char  *targv[];
  370.   {
  371.     register nptr  n;
  372.  
  373.     if( targc != 4 )
  374.     BAD_ARGC( 'D', targc, targv );
  375.  
  376.     n = GetNode( targv[1] );
  377.     n->nflags |= USERDELAY;
  378.     n->tplh = ns2d( atof( targv[2] ) );
  379.     n->tphl = ns2d( atof( targv[3] ) );
  380.   }
  381.  
  382.  
  383. /*
  384.  * add capacitance to a node (c sim command).
  385.  */
  386. private void ncap( targc, targv )
  387.   int   targc;
  388.   char  *targv[];
  389.   {
  390.     register nptr n, m;
  391.     float         cap;
  392.  
  393.     if( targc == 3 )
  394.       {
  395.     n = GetNode( targv[1] );
  396.     n->ncap += atof( targv[2] );
  397.       }
  398.     else if( targc == 4 )        /* two terminal caps    */
  399.       {
  400.     cap = atof( targv[3] ) / 1000;        /* ff to pf conversion */
  401.     n = GetNode( targv[1] );
  402.     m = GetNode( targv[2] );
  403.     if( n != m )            /* add cap to both nodes */
  404.       {
  405.         if( m != GND_node )    m->ncap += cap;
  406.         if( n != GND_node )    n->ncap += cap;
  407.       }
  408.     else if( n == GND_node )    /* same node, only GND makes sense */
  409.         n->ncap += cap;
  410.       }
  411.     else
  412.     BAD_ARGC( 'c', targc, targv );
  413.   }
  414.  
  415.  
  416. /*
  417.  * parse input line into tokens, filling up carg and setting targc
  418.  */
  419. private int parse_line( line, carg )
  420.   register char  *line;
  421.   register char  **carg;
  422.   {
  423.     register char  ch;
  424.     register int   targc;
  425.  
  426.     targc = 0;
  427.     while( ch = *line++ )
  428.       {
  429.     if( ch <= ' ' )
  430.         continue;
  431.     targc++;
  432.     *carg++ = line - 1;
  433.     while( *line > ' ' )
  434.         line++;
  435.     if( *line )
  436.         *line++ = '\0';
  437.       }
  438.     *carg = 0;
  439.     return( targc );
  440.   }
  441.  
  442.  
  443. private    int    R_error = FALSE;
  444. private    int    A_error = FALSE;
  445.  
  446.  
  447. private int input_sim( simfile )
  448.   char  *simfile;
  449.   {
  450.     FILE  *fin;
  451.     char  line[LSIZE];
  452.     char  *targv[MAXARGS];    /* tokens on current command line */
  453.     int   targc;        /* number of args on command line */
  454.     long  offset;        /* state of previously opened file */
  455.     int   olineno;
  456.  
  457.     if( (fin = fopen( simfile, "r" )) == NULL )
  458.       {
  459.     lprintf( stderr, "cannot open '%s' for sim input\n", simfile );
  460.     return( FALSE );
  461.       }
  462.     simfname = simfile;
  463.     lineno = 0;
  464.  
  465.     while( fgetline( line, LSIZE, fin ) != NULL )
  466.       {
  467.     lineno++;
  468.     targc = parse_line( line, targv );
  469.     if( targv[0] == NULL )
  470.         continue;
  471.     switch( targv[0][0] )
  472.       {
  473.         case '@' :
  474.         if( targc != 2 )
  475.           {
  476.             error( simfname, lineno, bad_argc_msg, '@', targc );
  477.             CheckErrs( WARN );
  478.             break;
  479.           }
  480.         offset = ftell( fin );
  481.         olineno = lineno;
  482.         (void) fclose( fin );
  483.         (void) input_sim( targv[1] );
  484.         if( (fin = fopen( simfile, "r" )) == NULL )
  485.           {
  486.             error( simfname, lineno, "can't re-open sim file '%s'\n",
  487.                simfile );
  488.             CheckErrs( WARN );
  489.             return( FALSE );
  490.           }
  491.         (void) fseek( fin, offset, 0 );
  492.         simfname = simfile;
  493.         lineno = olineno;
  494.         break;
  495.  
  496.         case '|' :
  497.         break;
  498.         case 'e' :
  499.         case 'n' :
  500.         newtrans( NCHAN, targc, targv );
  501.         break;
  502.         case 'p' :
  503.         newtrans( PCHAN, targc, targv );
  504.         break;
  505.         case 'd' :
  506.         newtrans( DEP, targc, targv );
  507.         break;
  508.         case 'r' :
  509.         newtrans( RESIST, targc, targv );
  510.         break;
  511.         case 'N' :
  512.         node_info( targc, targv );
  513.         break;
  514.         case 'M' :
  515.         nnode_info( targc, targv );
  516.         break;
  517.         case 'c' :
  518.         case 'C' :
  519.             ncap( targc, targv );
  520.         break;
  521.         case '=' :
  522.             alias( targc, targv );
  523.         break;
  524.         case 't' :
  525.             nthresh( targc, targv );
  526.         break;
  527.         case 'D' : 
  528.             ndelay( targc, targv );
  529.         break;
  530.         case 'R' : 
  531.         if( not R_error )    /* only warn about this 1 time */
  532.           {
  533.             lprintf( stderr,
  534.               "%s: Ignoring lumped-resistance ('R' construct)\n",
  535.               simfname );
  536.             R_error = TRUE;
  537.           }
  538.         break;
  539.         case 'A' :
  540.         if( not A_error )    /* only warn about this 1 time */
  541.           {
  542.             lprintf( stderr,
  543.               "%s: Ignoring attribute-line ('A' construct)\n",
  544.               simfname );
  545.             A_error = TRUE;
  546.           }
  547.         break;
  548.         case '<' : 
  549.         if( lineno == 1 and rd_netfile( fin, line ) )
  550.           {
  551.             (void) fclose( fin );
  552.             return( TRUE );
  553.           }
  554.         /* fall through if rd_netfile returns FALSE */
  555.         default :
  556.         error( simfname, lineno, "Unrecognized input line (%s)\n",
  557.           targv[0] );
  558.         CheckErrs( WARN );
  559.       }
  560.       }
  561.     (void) fclose( fin );
  562.     return( FALSE );
  563.   }
  564.  
  565.  
  566.  
  567. private void init_counts()
  568.   {
  569.     register int  i;
  570.  
  571.     for( i = 0; i < NTTYPES; i++ )
  572.     ntrans[i] = 0;
  573.     nnodes = naliases = 0;
  574.   }
  575.  
  576.  
  577. public int rd_network( simfile )
  578.   char  *simfile;
  579.   {
  580.     static int      firstcall = 1;
  581.  
  582.     if( firstcall )
  583.       {
  584.     rd_tlist = NULL;
  585.     init_hash();
  586.     init_counts();
  587.     init_listTbl();
  588.  
  589.     VDD_node = GetNode( "Vdd" );
  590.     VDD_node->npot = HIGH;
  591.     VDD_node->nflags |= (INPUT | POWER_RAIL);
  592.     VDD_node->head.inp = 1;
  593.     VDD_node->head.val = HIGH;
  594.     VDD_node->head.punt = 0;
  595.     VDD_node->head.time = 0;
  596.     VDD_node->head.t.r.rtime = VDD_node->head.t.r.delay = 0;
  597.     VDD_node->head.next = last_hist;
  598.     VDD_node->curr = &(VDD_node->head);
  599.  
  600.     GND_node = GetNode( "Gnd" );
  601.     GND_node->npot = LOW;
  602.     GND_node->nflags |= (INPUT | POWER_RAIL);
  603.     GND_node->head.inp = 1;
  604.     GND_node->head.val = LOW;
  605.     GND_node->head.punt = 0;
  606.     GND_node->head.time = 0;
  607.     GND_node->head.t.r.rtime = GND_node->head.t.r.delay = 0;
  608.     GND_node->head.next = last_hist;
  609.     GND_node->curr = &(GND_node->head);
  610.  
  611.     NEW_TRANS( tcap );
  612.     tcap->scache.t = tcap->dcache.t = tcap;
  613.     tcap->x.pos = 0;
  614.  
  615.     firstcall = 0;
  616.       }
  617.     nerrs = 0;
  618.  
  619.     isBinFile = input_sim( simfile );
  620.     if( nerrs > 0 )
  621.     exit( 1 );
  622.   }
  623.  
  624.  
  625. public void pTotalNodes()
  626.   {
  627.     lprintf( stdout, "%d nodes", nnodes );
  628.     if( naliases != 0 )
  629.     lprintf( stdout, ", %d aliases", naliases );
  630.     lprintf( stdout, "; " );
  631.   }
  632.  
  633.  
  634. public void pTotalTxtors()
  635.   {
  636.     int  i;
  637.  
  638.     lprintf( stdout, "transistors:" );
  639.     for( i = 0; i < NTTYPES; i++ )
  640.     if( ntrans[i] != 0 )
  641.         lprintf( stdout, " %s=%d", ttype[i], ntrans[i] );
  642.     if( tcap->x.pos != 0 )
  643.     lprintf( stdout, " shorted=%d", tcap->x.pos );
  644.     lprintf( stdout, "\n" );
  645.   }
  646.  
  647.  
  648. public void ConnectNetwork()
  649.   {
  650.     nptr  ndlist;
  651.  
  652.     pTotalNodes();
  653.  
  654.     ndlist = ( isBinFile ) ? bin_connect_txtors() : connect_txtors();
  655.  
  656.     make_parallel( ndlist );
  657.     make_stacks( ndlist );
  658.  
  659.     pTotalTxtors();
  660.     pParallelTxtors();
  661.     pStackedTxtors();
  662.   }
  663.